#include <ks0108.h>
#include <Arial14.h>         // proportional font
#include <SystemFont5x7.h>    // system font
#include <avr/pgmspace.h>
/////////////////////////////// Menus PROGMEM /////////////////////////////// 
/////
prog_char titel_0[] PROGMEM = "= Main menu =";   // "String 0" etc are strings to store - change to suit.
prog_char titel_1[] PROGMEM = ""; // tacho hat keine caption
prog_char titel_2[] PROGMEM = ""; // sprint hat keine caption
prog_char titel_3[] PROGMEM = "= Shown trips ="; // GPS hat keine caption
prog_char titel_4[] PROGMEM = "= Trips = ";
prog_char titel_5[] PROGMEM = "= Max speed =";
prog_char titel_6[] PROGMEM = "= AvG speed =";
prog_char titel_7[] PROGMEM = "";
prog_char titel_8[] PROGMEM = "= Setup =";
prog_char titel_9[] PROGMEM = "= Quick setup = ";

PROGMEM const char *menu_titel[10] = 	   // change "string_table" name to suit
{  
  titel_0,titel_1,titel_2,titel_3,titel_4,titel_5,titel_6,titel_7,titel_8,titel_9};
/////
/////
prog_char s_titel_0[] PROGMEM = "";
prog_char s_titel_1[] PROGMEM = "";
prog_char s_titel_2[] PROGMEM = "";
prog_char s_titel_3[] PROGMEM = "= Shown trips ="; // GPS hat keine caption
prog_char s_titel_4[] PROGMEM = "= Flasher 1 = ";
prog_char s_titel_5[] PROGMEM = "= Flasher 2 =";

PROGMEM const char *setup_titel[6] = 	   // change "string_table" name to suit
{  
  s_titel_0,s_titel_1,s_titel_2,s_titel_3,s_titel_4,s_titel_5};
/////
/////
prog_char main_m_0[] PROGMEM = " 1. Standard mode";   // "String 0" etc are strings to store - change to suit.
prog_char main_m_1[] PROGMEM = " 2. Sprint mode";
prog_char main_m_2[] PROGMEM = " 3. Fuel mode";
prog_char main_m_3[] PROGMEM = " 4. Trips";
prog_char main_m_4[] PROGMEM = " 5. Max speed";
prog_char main_m_5[] PROGMEM = " 6. Avg speed";
prog_char main_m_6[] PROGMEM = " 7. Calc amount";
prog_char main_m_7[] PROGMEM = " 8. Setup";
prog_char main_m_8[] PROGMEM = " 9. Quick setup";

PROGMEM const char *menu_main[9] = 	   // change "string_table" name to suit
{  
  main_m_0,main_m_1,main_m_2,main_m_3,main_m_4,main_m_5,main_m_6,main_m_7,main_m_8};
/////
///// 
prog_char trip_m_0[] PROGMEM = " NP    ";   // "String 0" etc are strings to store - change to suit.
prog_char trip_m_1[] PROGMEM = " Day   ";
prog_char trip_m_2[] PROGMEM = " Tour  ";
prog_char trip_m_3[] PROGMEM = " Fuel  ";
prog_char trip_m_4[] PROGMEM = " Q1Trip";
prog_char trip_m_5[] PROGMEM = " Q2Trip";
prog_char trip_m_6[] PROGMEM = " Q3Trip";
prog_char trip_m_7[] PROGMEM = " Saison";
prog_char trip_m_8[] PROGMEM = " Board ";

PROGMEM const char *menu_trip[9] = 	   // change "string_table" name to suit
{  
  trip_m_0,trip_m_1,trip_m_2,trip_m_3,trip_m_4,trip_m_5,trip_m_6,trip_m_7,trip_m_8};
/////
///// 
prog_char avg_m_0[] PROGMEM = " NP    ";   // "String 0" etc are strings to store - change to suit.
prog_char avg_m_1[] PROGMEM = " Day   ";
prog_char avg_m_2[] PROGMEM = " Tour  ";
prog_char avg_m_3[] PROGMEM = " Fuel  ";
prog_char avg_m_4[] PROGMEM = " Q1 avg";
prog_char avg_m_5[] PROGMEM = " Q2 avg";
prog_char avg_m_6[] PROGMEM = " Q3 avg";
prog_char avg_m_7[] PROGMEM = " Saison";
prog_char avg_m_8[] PROGMEM = " Board ";

PROGMEM const char *menu_avg[9] = 	   // change "string_table" name to suit
{  
  avg_m_0,avg_m_1,avg_m_2,avg_m_3,avg_m_4,avg_m_5,avg_m_6,avg_m_7,avg_m_8};
/////
///// 
prog_char max_speed_m_0[] PROGMEM = " NP    ";   // "String 0" etc are strings to store - change to suit.
prog_char max_speed_m_1[] PROGMEM = " Day   ";
prog_char max_speed_m_2[] PROGMEM = " Tour  ";
prog_char max_speed_m_3[] PROGMEM = " Fuel  ";
prog_char max_speed_m_4[] PROGMEM = " Q1 max";
prog_char max_speed_m_5[] PROGMEM = " Q2 max";
prog_char max_speed_m_6[] PROGMEM = " Q3 max";
prog_char max_speed_m_7[] PROGMEM = " Saison";
prog_char max_speed_m_8[] PROGMEM = " Board ";

PROGMEM const char *menu_max_speed[9] = 	   // change "string_table" name to suit
{  
  max_speed_m_0,max_speed_m_1,max_speed_m_2,max_speed_m_3,max_speed_m_4,max_speed_m_5,max_speed_m_6,max_speed_m_7,max_speed_m_8};
/////
///// 
prog_char setup_m_0[] PROGMEM = " Adjust Backlight";   // "String 0" etc are strings to store - change to suit.
prog_char setup_m_1[] PROGMEM = " Adjust Contrast";   // "String 0" etc are strings to store - change to suit.
prog_char setup_m_2[] PROGMEM = " Shown trip";
prog_char setup_m_3[] PROGMEM = " Flasher 1";
prog_char setup_m_4[] PROGMEM = " Flasher 2";
prog_char setup_m_5[] PROGMEM = " Reset mem";
prog_char setup_m_6[] PROGMEM = " Reset fuel";

PROGMEM const char *menu_setup[7] = 	   // change "string_table" name to suit
{  
  setup_m_0,setup_m_1,setup_m_2,setup_m_3,setup_m_4,setup_m_5,setup_m_6};
/////
///// 
prog_char trip_setup_m_0[] PROGMEM = " Fuel + Total";   // "String 0" etc are strings to store - change to suit.
prog_char trip_setup_m_1[] PROGMEM = " Fuel + NP";
prog_char trip_setup_m_2[] PROGMEM = " Fuel + Day";
prog_char trip_setup_m_3[] PROGMEM = " Fuel + Tour";
prog_char trip_setup_m_4[] PROGMEM = " Fuel + Q1";
prog_char trip_setup_m_5[] PROGMEM = " Fuel + Q2";
prog_char trip_setup_m_6[] PROGMEM = " Fuel + Q3";
prog_char trip_setup_m_7[] PROGMEM = " Fuel + Saison";
prog_char trip_setup_m_8[] PROGMEM = " Fuel + Board";

PROGMEM const char *menu_trip_setup[9] = 	   // change "string_table" name to suit
{  
  trip_setup_m_0,trip_setup_m_1,trip_setup_m_2,trip_setup_m_3,trip_setup_m_4,trip_setup_m_5,trip_setup_m_6,trip_setup_m_7,trip_setup_m_8};
/////
///// 
prog_char quick_setup_m_0[] PROGMEM = " NP Trip|Avg|Max";
prog_char quick_setup_m_1[] PROGMEM = " Day Trip|Avg|Max";
prog_char quick_setup_m_2[] PROGMEM = " Tour Trip|Avg|Max";
prog_char quick_setup_m_3[] PROGMEM = " Fuel Trip|Avg|Max";
prog_char quick_setup_m_4[] PROGMEM = " Q1 Trip|Avg|Max";   // "String 0" etc are strings to store - change to suit.
prog_char quick_setup_m_5[] PROGMEM = " Q2 Trip|Avg|Max";
prog_char quick_setup_m_6[] PROGMEM = " Q3 Trip|Avg|Max";
prog_char quick_setup_m_7[] PROGMEM = " Saison Trip|Avg|Max";

PROGMEM const char *menu_quick_setup[8] = 	   // change "string_table" name to suit
{  
  quick_setup_m_0,quick_setup_m_1,quick_setup_m_2,quick_setup_m_3,quick_setup_m_4,quick_setup_m_5,quick_setup_m_6,quick_setup_m_7};
/////
///// 
prog_char flasher_m_0[] PROGMEM = " Off"; 
prog_char flasher_m_1[] PROGMEM = " Shifting";
prog_char flasher_m_2[] PROGMEM = " Warning";


PROGMEM const char *menu_flasher[3] = 	   // change "string_table" name to suit
{  
  flasher_m_0,flasher_m_1,flasher_m_2};
/////
char menu_activ_menu[9][30];
/////////////////////////////// Menus PROGMEM /////////////////////////////// 
///// vars ////////////
boolean       menu_button_rechts_valid=true;
boolean       menu_button_links_valid=true;
boolean       menu_button_oben_valid=true;
boolean       menu_button_unten_valid=true;
int           menu_button_rechts=14;
int           menu_button_links=15;
int           menu_button_oben=16;
int           menu_button_unten=17;
int           menu_marker=0;
int           menu_start=0;
int           menu_ende=3;
int           menu_max=8;
char          char_buffer[20];
boolean       menu_preload;
///// vars ////////////

////// bei veränderung des state => einmaliges zeichen des menüs ///////
int menu_disp(){ // z.B. menu_state = 26
  Serial.println("menu_disp() called;");
  disp_zeile_bak[0]=0;
  disp_zeile_bak[1]=0;
  disp_zeile_bak[2]=0;
  disp_zeile_bak[3]=0;
  int   level[3]={ 
    ((int)floor(menu_state/100))%10,((int)floor(menu_state/10)) % 10,menu_state%10     }; 
  // [0][1][2]
  // 001 => im hauptmenü, tacho standart ausgewählt
  // 002 => im hautpmenü, sprint ausgewählt
  // 031 => im tank reset menü,erste position
  // 032 => im tank reset menü,zweite postion
  // 041 => display setup position 1
  // 011 => standart anzeige
  // 340 => im Tacho reset, Trip4, [menu_button_rechts] -> also aktion nötig
  menu_button_rechts_valid=true;
  menu_button_links_valid=true;
  menu_button_oben_valid=true;
  menu_button_unten_valid=true;
  
  ///////////////////// im hauptmenü nach links => tacho ////////// 
  if(level[0]==0 && level[1]==0 && level[2]==0){
    menu_state=11;
    menu_disp();
  }
  ///////////////////// im hauptmenü nach links => tacho //////////
  ///////////////////// Hauptmenu //////////////////////////  
  else if(level[0]==0 && level[1]==0) {
    // Menu vorbereiten
    for(int a=0;a<(sizeof(menu_main)/sizeof(menu_main[0]));a++){
      strcpy_P(menu_activ_menu[a], (char*)pgm_read_word(&(menu_main[a])));   
      menu_max=a;
    };      
    // Menu vorbereiten
    menu_draw(level[0],level[1],level[2]);     
  } 
  //////////////////////// Einmaliges Setup des Standart Tacho ////////////////////////////
  else if(level[0]==0 && level[1]==1 ){ 
    GLCD.ClearScreen();
    Serial.println("Bin jetzt im Tacho menu, zeichne icons");
    draw_oil(0,0);
    draw_fuel(88,55);
    draw_air(88,0);
    draw_clock(4,58);

    menu_button_rechts_valid=false; // nach rechts gehen geht nicht 
    for(int i=0;i<sizeof(disp_zeile_bak)/sizeof(disp_zeile_bak[0]);i++){
      disp_zeile_bak[i]=0;
    };
  } 
  //////////////////////// Einmaliges Setup des Sprint Tacho ////////////////////////////
  else if(level[0]==0 && level[1]==2 && level[2]==1){ 
    GLCD.ClearScreen();
    GLCD.GotoXY(0,0);
    GLCD.Puts("SprintMode");
    sprint_done=false;
    sprint_lock=false;
    menu_button_rechts_valid=false;
    menu_button_oben_valid=false;
    menu_button_unten_valid=false;
    for(int i=0;i<sizeof(disp_zeile_bak)/sizeof(disp_zeile_bak[0]);i++){
      disp_zeile_bak[i]=0;
    };
  } 
  //////////////////////// Einmaliges Setup des GPS Tacho ////////////////////////////
  else if(level[0]==0 && level[1]==3 && level[2]==1){ 
    GLCD.ClearScreen();
    GLCD.GotoXY(0,0);
    GLCD.Puts("Fuel Monitor");
    menu_button_rechts_valid=false;
    menu_button_oben_valid=false;
    menu_button_unten_valid=false;
  }  
  /////||||||||||||||||||| TRIP |||||||||||||||||||\\\\\\\\\\\\\\\\\\\
  //////////////////////// Trip Menu ////////////////////////////
  else if(level[0]==0 && level[1]==4) {
    // Menu vorbereiten
    for(int a=0;a<(sizeof(menu_trip)/sizeof(menu_trip[0]));a++){
      strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_trip[a]))); 
      sprintf(menu_activ_menu[a],"%s   %5lu,%02i km",char_buffer,(unsigned long)floor(trip_dist[a]/1000),(int)floor((trip_dist[a]%1000)/10)); 
      menu_max=a;
    };      
    menu_draw(level[0],level[1],level[2]);
  } 
  ///////////////////// frage nach reset eines tripstand ////////////////////////// 
  else if(level[0]==4 && level[2]==1 && level[1]<9) { 
    strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_trip[level[1]-1]))); 
    sprintf(char_buffer,"%s   %5lu,%02i km",char_buffer,(unsigned long)floor(trip_dist[level[1]-1]/1000),(int)floor((trip_dist[level[1]-1]%1000)/10)); 
    menu_yesno("Really reset","   Trip:",char_buffer);
  } 
  ///////////////////// frage nach reset eines tripstand ////////////////////////// 
  else if(level[0]==4 && level[2]==2) { 
    // Menu vorbereiten
    trip_dist[level[1]-1]=0;
    strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_trip[level[1]-1])));
    menu_del_conf(char_buffer,"   trip reseted");
    storage_outdated=true;  
  } 
  /////||||||||||||||||||| TRIP |||||||||||||||||||\\\\\\\\\\\\\\\\\\\
  /////||||||||||||||||||| max |||||||||||||||||||\\\\\\\\\\\\\\\\\\\
  //////////////////////// max Menu ////////////////////////////
  else if(level[0]==0 && level[1]==5) {
    // Menu vorbereiten
    for(int a=0;a<(sizeof(menu_max_speed)/sizeof(menu_max_speed[0]));a++){
      strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_max_speed[a]))); 
      sprintf(menu_activ_menu[a],"%s      %3i km/h",char_buffer,(int)max_speed[a]); 
      menu_max=a;
    };      
    menu_draw(level[0],level[1],level[2]);
  } 
  ///////////////////// frage nach reset eines max stands ////////////////////////// 
  else if(level[0]==5 && level[2]==1 && level[1]<9) {    
    strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_max_speed[level[1]-1]))); 
    sprintf(char_buffer,"%s      %3i km/h",char_buffer,(int)max_speed[level[1]-1]);   
    menu_yesno("Really reset","max speed:",char_buffer);
  } 
  ///////////////////// frage nach reset eines max_stand ////////////////////////// 
  else if(level[0]==5 && level[2]==2) { 
    // Menu vorbereiten
    max_speed[level[1]-1]=0;
    strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_max_speed[level[1]-1])));
    menu_del_conf(char_buffer,"max speed reseted");
    storage_outdated=true;
  } 
  /////||||||||||||||||||| max |||||||||||||||||||\\\\\\\\\\\\\\\\\\
  /////||||||||||||||||||| avg |||||||||||||||||||\\\\\\\\\\\\\\\\\\\
  //////////////////////// avg overview Menu ////////////////////////////
  else if(level[0]==0 && level[1]==6) {
    // Menu vorbereiten
    for(int a=0;a<(sizeof(menu_avg)/sizeof(menu_avg[0]));a++){
      strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_avg[a]))); 
      sprintf(menu_activ_menu[a],"%s   %3i,%02i km/h",char_buffer,(int)floor(avg_speed[a]/avg_timebase[a]),(int)floor(avg_speed[a]*100/avg_timebase[a])%100); 
      menu_max=a;
    };      
    menu_draw(level[0],level[1],level[2]);
  } 
  ///////////////////// frage nach reset eines avg stands ////////////////////////// 
  else if(level[0]==6 && level[2]==1 && level[1]<9) { 
    strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_avg[level[1]-1]))); 
    sprintf(char_buffer,"%s   %3i,%02i km/h",char_buffer,(int)floor(avg_speed[level[1]-1]/avg_timebase[level[1]-1]),(int)floor(avg_speed[level[1]-1]*100/avg_timebase[level[1]-1])%100); 
    menu_yesno("Really reset","avg speed:",char_buffer);
  } 
  ///////////////////// frage nach reset eines avg_stand ////////////////////////// 
  else if(level[0]==6 && level[2]==2) { 
    // Menu vorbereiten
    avg_speed[level[1]-1]=0;
    avg_timebase[level[1]-1]=0;
    strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_avg[level[1]-1])));
    menu_del_conf(char_buffer,"avg speed reseted");
    storage_outdated=true;
  } 
  /////||||||||||||||||||| avg |||||||||||||||||||\\\\\\\\\\\\\\\\\\
  //////////////////////// fuel added /////////////////////////////
  else if(level[0]==0 && level[1]==7 && level[2]==1){
    GLCD.ClearScreen();
    GLCD.GotoXY(10,20);
    GLCD.Puts("Added fuel amount:");
    GLCD.GotoXY(32,30);
    sprintf(char_buffer,"%2i,%0i",(int)floor(fuel_added/10),(int)fuel_added%10);
    GLCD.Puts(char_buffer);
    GLCD.Puts(" l");
  }
  else if(level[0]==0 && level[1]==7 && (level[2]==9 || level[2]==2)){
    if(level[2]==9) { 
      fuel_added++; 
    }
    else { 
      fuel_added--; 
    };
    if(fuel_added<1){ 
      fuel_added=1; 
    }
    else if(fuel_added>800) { 
      fuel_added=800; 
    };
    GLCD.FillRect(22,30,60,10,WHITE);
    GLCD.GotoXY(38,30);
    sprintf(char_buffer,"%2i,%0i",(int)floor(fuel_added/10),(int)fuel_added%10);
    GLCD.Puts(char_buffer);
    GLCD.Puts(" l");
    menu_state=71;
  }
  else if(level[0]==7){
    GLCD.ClearScreen();
    GLCD.GotoXY(24,20);
    GLCD.Puts("Average need: ");
    GLCD.GotoXY(27,30);
    sprintf(char_buffer,"%2i,%0i",(int)floor(fuel_added*10/(trip_dist[3]/1000)),(int)(fuel_added*100/(trip_dist[3]/1000))%10);
    GLCD.Puts(char_buffer);
    GLCD.Puts(" l/100km");
    GLCD.GotoXY(32,47);
    GLCD.Puts("All Fuel");
    GLCD.GotoXY(22,55);
    GLCD.Puts("storages reseted");
    fuel_set(0,0,-1);
    trip_dist[3]=0;
    avg_timebase[3]=0;
    avg_speed[3]=0;
    max_speed[3]=0;
    menu_state=71;
    storage_outdated=true;
  }
  //////////////////////// fuel added /////////////////////////////
  //////////////////////// Setup Menu ////////////////////////////
  else if(level[0]==0 && level[1]==8) {
    // Menu vorbereiten
    for(int a=0;a<(sizeof(menu_setup)/sizeof(menu_setup[0]));a++){
      strcpy_P(menu_activ_menu[a], (char*)pgm_read_word(&(menu_setup[a]))); 
      menu_max=a;
    };      
    menu_draw(level[0],level[1],level[2]);
    menu_preload=true;
  } 
  ///////////////////// Helligkeitseinstellung ////////////////////////// 
  else if(level[0]==8 && level[1]==1) { 
    // Pushed down
    Serial.print("menu ");
    Serial.print(menu_state);
    Serial.print("\n");
    if(level[2]>2){
      disp_brightness++;
      Serial.print("Disp_brightness ");
      Serial.print(disp_brightness);
      Serial.print("\n");
      menu_state=811; 
    }
    // Pushed up
    else if(level[2]==2){
      disp_brightness--;
      menu_state=811; 
    };
    if(disp_brightness>99) { 
      disp_brightness=100; 
    }
    if(disp_brightness<1) { 
      disp_brightness=0; 
    }
    GLCD.ClearScreen();
    GLCD.GotoXY(20,28);
    sprintf(char_buffer,"Backlight: %3i%%",disp_brightness);
    GLCD.Puts(char_buffer);     
    analogWrite(disp_backlight_pin,round(disp_brightness*255/100));
    // store to eeprom
    byte tempByte = (disp_brightness & 0xFF);
    EEPROM.write(5,tempByte);  
    delay(4);
  } 
  ///////////////////// Kontrasteinstellung ////////////////////////// 
    else if(level[0]==8 && level[1]==2) { 
    // Pushed down
    Serial.print("menu ");
    Serial.print(menu_state);
    Serial.print("\n");
    if(level[2]>2){
      disp_contrast++;
      menu_state=821; 
    }
    // Pushed up
    else if(level[2]==2){
      disp_contrast--;
      menu_state=821; 
    };
    if(disp_contrast>254) { 
      disp_contrast=255; 
    }
    if(disp_contrast<200) { 
      disp_contrast=200; 
    }
    GLCD.ClearScreen();
    GLCD.GotoXY(35,10);
    sprintf(char_buffer,"Display");
    GLCD.Puts(char_buffer);    
    GLCD.GotoXY(20,18);
    sprintf(char_buffer,"contrast: %2i",  (disp_contrast-200));
    GLCD.Puts(char_buffer);    
    GLCD.FillRect(20,30,88,10,WHITE);
    GLCD.DrawRect(20,30,88,10,BLACK);
    GLCD.FillRect(21,31,round(86*(disp_contrast-200)/55),8,BLACK);
    
    draw_sun(10,35,true);
    draw_sun(118,35,false);
    
    Serial.println("writing to display");
    Serial.print("Disp_contrast ");
    Serial.print(disp_contrast);
    Serial.print("\n");
    
    analogWrite(disp_contrast_pin,disp_contrast);
    // store to eeprom
    byte tempByte = (disp_contrast & 0xFF);
    EEPROM.write(149,tempByte);  
    delay(4);
  } 
  ///////////////////// trip show setup //////////////////////////
  else if(level[0]==8 && level[1]==3 ) {
    if(menu_preload){ // wird im Menü davor auf true gesetzt, erlaubt vorpositionieren des menüs.
      menu_preload=false; // damit beim ändern der preload nicht ausgeführt wird.
      level[2]=trip_mode;
      menu_state=level[0]*100+level[1]*10+level[2]; // menu_state muss angepasst werden.
      if((level[2])>4){  // positionierung des Markers
        menu_marker=3; 
        menu_start=level[2]-4; 
        menu_ende=level[2]-1; 
      }
      else { 
        menu_marker=level[2]-1; 
        menu_start=0; 
        menu_ende=3; 
      };
    } 
    else { // speichern des neuen Werts 
      trip_mode=level[2];
      byte tempByte = (trip_mode & 0xFF);
      EEPROM.write(2,tempByte);
    };
    for(int a=0;a<(sizeof(menu_trip_setup)/sizeof(menu_trip_setup[0]) );a++){
      strcpy_P(menu_activ_menu[a], (char*)pgm_read_word(&(menu_trip_setup[a]))); 
      menu_max=a;
    };      
    menu_draw(level[0],level[1],level[2]);
    // hier noch 2do
  } 
  ///////////////////// flasher setup //////////////////////////
  else if(level[0]==8 && (level[1]==4 || level[1]==5)) {
    if(menu_preload){ // wird im Menü davor auf true gesetzt, erlaubt vorpositionieren des menüs.
      menu_preload=false; // damit beim ändern der preload nicht ausgeführt wird.
      if(level[1]==3){    
        level[2]=flasher_1_mode;    
      } 
      else {              
        level[2]=flasher_2_mode;    
      };      
      menu_state=level[0]*100+level[1]*10+level[2]; // menu_state muss angepasst werden.
      if((level[2])>4){  // positionierung des Markers
        menu_marker=3; 
        menu_start=level[2]-4; 
        menu_ende=level[2]-1; 
      }
      else { 
        menu_marker=level[2]-1; 
        menu_start=0; 
        menu_ende=3; 
      };
    } 
    else { // speichern des neuen Werts 
      if(level[1]==4){
        flasher_1_mode=level[2];
        byte tempByte = (flasher_1_mode & 0xFF);
        EEPROM.write(0,tempByte);
      }
      else{
        flasher_2_mode=level[2];
        byte tempByte = (flasher_2_mode & 0xFF);
        EEPROM.write(1,tempByte);
      };
    };

    for(int a=0;a<(sizeof(menu_flasher)/sizeof(menu_flasher[0]) );a++){
      strcpy_P(menu_activ_menu[a], (char*)pgm_read_word(&(menu_flasher[a]))); 
      menu_max=a;
    };      
    menu_draw(level[0],level[1],level[2]);
    // hier noch 2do
  } 
   ///////////////////// reset setup //////////////////////////
  else if(level[0]==8 && level[1]==6 && level[2]==1) {
    menu_yesno("Really reset","total mem","");
  }
  else if(level[0]==8 && level[1]==6 && level[2]==2) {
    byte tempByte;
    tempByte = ((int)1 & 0xFF);
    EEPROM.write(0, tempByte); // tripmode=1
    EEPROM.write(1, tempByte); // flasher1=1
    EEPROM.write(2, tempByte); // flasher2=1
    tempByte = ((int)100 & 0xFF);    
    EEPROM.write(5, tempByte); // display=100
    tempByte = ((int)92 & 0xFF);    
    EEPROM.write(150, tempByte); // fuel_max=9.2 l
    tempByte = ((int)0 & 0xFF);    
    EEPROM.write(151, tempByte); // fuel_step=0
    EEPROM.write(152, tempByte); // fuel_counter=0
    
    unsigned long temp_long=0;
    for(int i=6;i<31;i=i+4){
      EEPROM_writeUnsignedLong(i,temp_long); // erase trip_mode=0
    };
    for(int i=38;i<131;i=i+4){
      EEPROM_writeUnsignedLong(i,temp_long); // erase avg_timbase,avg_speed,max_mode=0
    };
    menu_del_conf("The memory","has been reset");
    menu_state=11;
    setup(); 
  }
  /////////// adjust  //////////
  else if(level[0]==8 && level[1]==7 && level[2]==1) {
     menu_yesno("Really reset","fuel mem","");
  }
  else if(level[0]==8 && level[1]==7 && level[2]==2) {
    byte tempByte = (95 & 0xFF);
    EEPROM.write(150,tempByte); // 95=max -> 8.5 L
    EEPROM.write(151,0); // 95=max -> 9.5 L
    EEPROM.write(152,0); // 95=max -> 9.5 L
    fuel_set(0,0,95);
    menu_del_conf("Fuel memory","   has been reset");
    menu_state=11;
    menu_disp();
  }
  //////////////////// quick start //////////////////////////
  else if(level[0]==0 && level[1]==9){
    for(int a=0;a<(sizeof(menu_quick_setup)/sizeof(menu_quick_setup[0]));a++){
      strcpy_P(menu_activ_menu[a], (char*)pgm_read_word(&(menu_quick_setup[a])));
      menu_max=a;
    };      
    menu_draw(level[0],level[1],level[2]);
  }
  else if(level[0]==9){
    max_speed[level[1]-1]=0;
    avg_timebase[level[1]-1]=0;
    avg_speed[level[1]-1]=0;
    trip_dist[level[1]-1]=0;
    // prepare save 
    storage_outdated=true;

    GLCD.ClearScreen();
    GLCD.GotoXY(55,25);
    sprintf(char_buffer,"cleared.",level[1]);
    GLCD.Puts(char_buffer);
    delay(800);
    menu_state=11;
    menu_max=8;
    menu_disp();
  }
  ///////////////////// "notfall" //////////////////////////
  else {
    menu_back();
  };
  ///////////////////// E N D E ////////////////////////// 
};
////// bei veränderung des state => einmaliges zeichen des menüs ///////

//// ein rückschritt im menü machen ////////
void menu_back(){
  int return_value=floor(menu_state/10);
  if((return_value%10)>4){ 
    menu_marker=3; 
    menu_start=(return_value%10)-4; 
    menu_ende=(return_value%10)-1; 
  }
  else { 
    menu_marker=(return_value%10)-1; 
    menu_start=0; 
    menu_ende=3; 
  };
  menu_state=return_value;
  if(floor(menu_state/100)==0 && ((int)floor(menu_state/10))%10 == 0){ 
    menu_button_links_valid=false; 
  };
};
//// ein rückschritt im menü machen ////////

/// eine rückfrage: soll ich wirklich löschen ////
void menu_yesno(char first[30],char second[30],char third[30]){
  // Menu vorbereiten
  GLCD.ClearScreen();
  GLCD.GotoXY(24,10);
  GLCD.Puts(first);
  GLCD.GotoXY(28,20);
  GLCD.Puts(second);
  GLCD.GotoXY(0,30);
  GLCD.Puts(third);
  GLCD.GotoXY(0,55);
  GLCD.Puts("yes=>down    no=>left");
  menu_button_rechts_valid=false;
  menu_button_oben_valid=false;
};
/// eine rückfrage: soll ich wirklich löschen ////

/// bestätigen eines löschens ///
void menu_del_conf(char first[20],char second[20]){
  GLCD.ClearScreen();
  GLCD.GotoXY(38,20);
  GLCD.Puts(first);
  GLCD.GotoXY(12,30);
  GLCD.Puts(second);
  delay(1200);
  menu_back();   
  menu_disp();
};
/// bestätigen eines löschens ///

///// ein text menü zeichnen ////////////
void menu_draw(int level_0,int level_1,int level_2){
  int   y=12;
  int   x=0;  
  // Menu Caption
  GLCD.FillRect(0,0,128,12,WHITE);
  GLCD.GotoXY(0,0);
  if(level_0==8){ // menu 8 hat eigene Titel
    strcpy_P(char_buffer, (char*)pgm_read_word(&(setup_titel[level_1])));
  } else {
    strcpy_P(char_buffer, (char*)pgm_read_word(&(menu_titel[level_1])));
  };
  
  GLCD.Puts(char_buffer);
  sprintf(char_buffer,"%i-%i-%i",level_0,level_1,level_2);
  GLCD.GotoXY(98,0);
  GLCD.Puts(char_buffer);
  // Menu Caption
  // Menu ausgeben
  if(menu_ende>menu_max){
    menu_ende=menu_max;
  };
  for(int k=menu_start;k<=menu_ende;k++){
    GLCD.FillRect(x,y,126,12,WHITE);
    GLCD.GotoXY(x,y);
    GLCD.Puts(menu_activ_menu[k]);
    y=y+12; // abstand festlegen
  };
  GLCD.FillRect(0,y,128,68-y,WHITE);
  // rect
  y=10+menu_marker*12;
  GLCD.InvertRect(1, y+1, 124, 7);
  GLCD.DrawRoundRect(0,y+1,126,8,1,BLACK); // koordinaten festelen
  // rect
  // Menu ausgeben
};
///// ein text menü zeichnen ////////////

///// zyklisches abfragen der buttons ////////////
int menu_button_test(){
  if(millis()>(menu_button_time+menu_button_timeout) || (menu_button_first_push>0 && millis()>(menu_button_first_push+menu_button_fast_delay)) && millis()>(menu_button_fast_timeout+menu_button_time)){ // halbe sek timeout
    int   level[3]={ 
      ((int)floor(menu_state/100))%10,((int)floor(menu_state/10)) % 10,menu_state%10                                    }; 
    if(digitalRead(menu_button_rechts)==1 && menu_button_rechts_valid){
      if(menu_button_first_push==0){
        menu_button_first_push=millis();
      };
      Serial.println("menu_button_rechts");
      menu_start=0;
      menu_ende=3;
      menu_marker=0;
      return (menu_state*10)+1;
    } 
    else if(digitalRead(menu_button_links)==1 && menu_button_links_valid){
      if(menu_button_first_push==0){
        menu_button_first_push=millis();
      };
      Serial.println("menu_button_links");
      int return_value=floor(menu_state/10);
      if((return_value%10)>4){ 
        menu_marker=3; 
        menu_start=(return_value%10)-4; 
        menu_ende=(return_value%10)-1; 
      }
      else { 
        menu_marker=(return_value%10)-1; 
        menu_start=0; 
        menu_ende=3; 
      };

      return return_value;
    } 
    else if(digitalRead(menu_button_oben)==1 && menu_button_oben_valid){
      if(menu_button_first_push==0){
        menu_button_first_push=millis();
      };
      Serial.println("menu_button_oben");
      // move menu
      menu_marker--;
      if(menu_marker<0){
        menu_marker++;
        menu_start--;
        menu_ende--;
        if(menu_start<0){
          menu_start=menu_max-3;
          menu_ende=menu_max;
          menu_marker=3;
          if(menu_max<3){
            menu_marker=menu_max; 
            menu_start+=(3-menu_max);
            menu_ende+=(3-menu_max);
          };
        };
      };

      // reset backup
      if(level[0]==0 && level[1]==0){
        for(int i=0;i<sizeof(disp_zeile_bak)/sizeof(disp_zeile_bak[0]);i++){
          disp_zeile_bak[i]=0;
        };
      };

      //recalc level
      level[2]--;
      if(level[2]==0){
        level[2]=menu_max+1;
      };
      int return_value=level[0]*100+level[1]*10+level[2];
      return (return_value); // -1
    } 
    else if(digitalRead(menu_button_unten)==1 && menu_button_unten_valid){
      if(menu_button_first_push==0){
        menu_button_first_push=millis();
      };
      Serial.println("menu_button_unten");
      // move menu
      menu_marker++;
      int limit=3;
      if(menu_max<3){
        limit=menu_max;
      };
      if(menu_marker>limit){
        menu_marker--;
        menu_start++;
        menu_ende++;
        if(menu_ende>menu_max){ // HIER
          menu_marker=0;
          menu_start=0;
          menu_ende=3;
        };
      };

      // reset backup
      if(level[0]==0 && level[1]==0){
        for(int i=0;i<sizeof(disp_zeile_bak)/sizeof(disp_zeile_bak[0]);i++){
          disp_zeile_bak[i]=0;
        };
      };

      //      Serial.print("Level0 vorher:");
      //      Serial.print(level[0]);
      //      Serial.print("\n");

      //recalc level
      level[2]++;
      if(level[2]>(menu_max+1)){
        level[2]=1;
      };
      int return_value=level[0]*100+level[1]*10+level[2];
      //      Serial.print("returne jetzt:");
      //      Serial.print(return_value);
      //      Serial.print("\n");
      return (return_value);
    }
    else {
      menu_button_first_push=0;
      return -1;
    };
    // menu_button_unten zumenu_ende
  };    
  return -1;
};
///// zyklisches abfragen der buttons ////////////

void menu_init(){
  pinMode(menu_button_rechts, INPUT);
  pinMode(menu_button_links, INPUT);
  pinMode(menu_button_oben, INPUT);
  pinMode(menu_button_unten, INPUT);
  pinMode(disp_backlight_pin, OUTPUT); 
  pinMode(disp_contrast_pin, OUTPUT); 
  pinMode(disp_gnd_pin, OUTPUT); 
  digitalWrite(disp_gnd_pin,LOW);
  Serial.println("Menu init done");
};



